简单研究C++ 对象内存布局

关于C++对象布局 看了大佬的博客,大佬的博客过于久远格式比较清奇,我整理了,顺便改了程序能够在 64位机运行。

单一的一般继承

在这里插入图片描述
通俗的讲,一层层下去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
using namespace std;

class Parent
{
public:
long iparent;//因为是64位机,所以改成了 long

Parent() : iparent(10) {}
virtual void f() { cout << " Parent::f()" << endl; }
virtual void g() { cout << " Parent::g()" << endl; }
virtual void h() { cout << " Parent::h()" << endl; }
};

class Child : public Parent
{
public:
long ichild;
Child() : ichild(100) {}
virtual void f() { cout << "Child::f()" << endl; }
virtual void g_child() { cout << "Child::g_child()" << endl; }
virtual void h_child() { cout << "Child::h_child()" << endl; }
};
class GrandChild : public Child
{
public:
long igrandchild;
GrandChild() : igrandchild(1000) {}
virtual void f() { cout << "GrandChild::f()" << endl; }
virtual void g_child() { cout << "GrandChild::g_child()" << endl; }
virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }
};
typedef void (*Fun)(void);
int main()
{

GrandChild gc;
long **pVtab = (long **)&gc;
Fun pFun;
cout << "[0] GrandChild::_vptr->" << endl;
for (int i = 0; (Fun)pVtab[0][i] != NULL; i += 2)
{
pFun = (Fun)pVtab[0][i];
cout << " [" << i << "] ";
pFun();
}
printf("start offet:%llx\n", pVtab);
cout << "[1] Parent.iparent = " << (long)((pVtab[1])) << endl;
cout << "[2] Child.ichild = " << (long)(pVtab[2]) << endl;
cout << "[3] GrandChild.igrandchild = " << (long)(pVtab[3]) << endl;
}

输出结果

1
2
3
4
5
6
7
8
[0] GrandChild::_vptr->
[0] GrandChild::f()
[2] Parent::h()
[4] Child::h_child()
start offet:7ffee4956f80
[1] Parent.iparent = 10
[2] Child.ichild = 100
[3] GrandChild.igrandchild = 1000

在这里插入图片描述

顺便我们用gdb 看一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
list
40 {
41 pFun = (Fun)pVtab[0][i];
42 cout << " [" << i << "] ";
43 pFun();
44 }
45 printf("start offet:%llx\n", pVtab);
46 cout << "[1] Parent.iparent = " << (long)((pVtab[1])) << endl;
47 cout << "[2] Child.ichild = " << (long)(pVtab[2]) << endl;
48 cout << "[3] GrandChild.igrandchild = " << (long)(pVtab[3]) << endl;
49 }

p pVtab
$1 = (long **) 0x7fffffffcb90

x /10xg 0x7fffffffcb90
0x7fffffffcb90: 0x0000555555755ce0(你可以继续找下去可以找到具体函数地址) 0x000000000000000a(10)
0x7fffffffcba0: 0x0000000000000064(100) 0x00000000000003e8(1000)
0x7fffffffcbb0: 0x000000000000008e 0x000055555555509a
0x7fffffffcbc0: 0x00007fffffffcb90 0x0000000655554bf0
0x7fffffffcbd0: 0x00007fffffffccc0 0x0000000000000000

多重继承

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include<iostream>
using namespace std;
class Base1
{
public:
long ibase1;
Base1() : ibase1(0x10) {}
virtual void f() { cout << "Base1::f()" << endl; }
virtual void g() { cout << "Base1::g()" << endl; }
virtual void h() { cout << "Base1::h()" << endl; }
};
class Base2
{
public:
long ibase2;
Base2() : ibase2(0x20) {}
virtual void f() { cout << "Base2::f()" << endl; }
virtual void g() { cout << "Base2::g()" << endl; }
virtual void h() { cout << "Base2::h()" << endl; }
};
class Base3
{
public:
long ibase3;
Base3() : ibase3(0x30) {}
virtual void f() { cout << "Base3::f()" << endl; }
virtual void g() { cout << "Base3::g()" << endl; }
virtual void h() { cout << "Base3::h()" << endl; }
};
class Derive : public Base1,
public Base2,
public Base3
{
public:
long iderive;
Derive() : iderive(0x100) {}
virtual void f() { cout << "Derive::f()" << endl; }
virtual void g1() { cout << "Derive::g1()" << endl; }
};
typedef void (*Fun)(void);
int main()
{
Derive d;
long **pVtab = (long **)&d;
Fun pFun;
cout<<hex;
cout << "[0] Base1::_vptr->" << endl;
pFun = (Fun)pVtab[0][0];
cout << " [0] ";
pFun();
pFun = (Fun)pVtab[0][1];
cout << " [1] ";
pFun();
pFun = (Fun)pVtab[0][2];
cout << " [2] ";
pFun();
pFun = (Fun)pVtab[0][3];
cout << " [3] ";
pFun();
pFun = (Fun)pVtab[0][4];
cout << " [4] ";
cout << pFun << endl;
cout << "[1] Base1.ibase1 = " << (long)(pVtab[1]) << endl;
long s = sizeof(Base1) / 8;
cout << "[" << s << "] Base2::_vptr->" << endl;
pFun = (Fun)pVtab[s][0];
cout << " [0] ";
pFun();
cout << " [1] ";
pFun=(Fun)pVtab[s][1];
pFun();
pFun = (Fun)pVtab[s][2];
cout << " [2] ";
pFun();
pFun = (Fun)pVtab[s][3];
cout << " [3] ";
cout << pFun << endl;
cout << "[" << s + 1 << "] Base2.ibase2 = " << (long)(pVtab[s + 1]) << endl;
s = s + sizeof(Base2) / 8;
cout << "[" << s << "] Base3::_vptr->" << endl;
pFun = (Fun)pVtab[s][0];
cout << " [0] ";
pFun();
pFun = (Fun)pVtab[s][1];
cout << " [1] ";
pFun();
pFun = (Fun)pVtab[s][2];
cout << " [2] ";
pFun();
pFun = (Fun)pVtab[s][3];
cout << " [3] ";
cout << pFun << endl;
s++;
cout << "[" << s << "] Base3.ibase3 = " << (long)pVtab[s] << endl;
s++;
cout << "[" << s << "] Derive.iderive = " << (long)pVtab[s] << endl;
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[0] Base1::_vptr->
[0] Derive::f()
[1] Base1::g()
[2] Base1::h()
[3] Derive::g1()
[4] 1//这个表示最后一个
[1] Base1.ibase1 = 10
[2] Base2::_vptr->
[0] Derive::f()
[1] Base2::g()
[2] Base2::h()
[3] 1
[3] Base2.ibase2 = 20
[4] Base3::_vptr->
[0] Derive::f()
[1] Base3::g()
[2] Base3::h()
[3] 0
[5] Base3.ibase3 = 30
[6] Derive.iderive = 100

用GDB看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-exec p pVtab
$1 = (long **) 0x7fffffffcb80

-exec x /10xg 0x7fffffffcb80
0x7fffffffcb80: 0x0000555555756c50 0x0000000000000010
0x7fffffffcb90: 0x0000555555756c80 0x0000000000000020
0x7fffffffcba0: 0x0000555555756ca8 0x0000000000000030
0x7fffffffcbb0: 0x0000000000000100 0x0000000000000000
0x7fffffffcbc0: 0x000055555555583e 0x00007fffffffcb80

-exec x /10xg 0x0000555555756c50
0x555555756c50 <_ZTV6Derive+16>: 0x000055555555583e 0x00005555555555be
0x555555756c60 <_ZTV6Derive+32>: 0x00005555555555f6 0x0000555555555882
0x555555756c70 <_ZTV6Derive+48>: 0xfffffffffffffff0 0x0000555555756d38
0x555555756c80 <_ZTV6Derive+64>: 0x000055555555587b 0x000055555555568c
0x555555756c90 <_ZTV6Derive+80>: 0x00005555555556c4 0xffffffffffffffe0

-exec x /10xg 0x000055555555583e (不知道为啥其他查看其他几个虚表,和这个值不一样,但是也指向这个函数)
0x55555555583e <Derive::f()>: 0x10ec8348e5894855 0x57358d48f87d8948
0x55555555584e <Derive::f()+16>: 0x18083d8d48000001 0x48fffff453e80020
0x55555555585e <Derive::f()+32>: 0x201791058b48c289 0xe8d78948c6894800
0x55555555586e <Derive::f()+48>: 0x48c3c990fffff45e 0xef8348c3eb20ef83
0x55555555587e <_ZThn16_N6Derive1fEv+3>: 0xe589485590bdeb10 0xf87d894810ec8348

在这里插入图片描述

重复继承

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <iostream>
using namespace std;
class B
{
public:
long ib;
char cb;

public:
B() : ib(0), cb('B')
{
}

virtual void
f()
{
cout << "B::f()" << endl;
}
virtual void Bf() { cout << "B::Bf()" << endl; }
};

class B1 : public B
{
public:
long ib1;
char cb1;

public:
B1() : ib1(11), cb1('1')
{
}
virtual void
f()
{
cout << "B1::f()" << endl;
}
virtual void f1() { cout << "B1::f1()" << endl; }
virtual void Bf1() { cout << "B1::Bf1()" << endl; }
};

class B2 : public B
{
public:
long ib2;
char cb2;

public:
B2() : ib2(12), cb2('2')
{
}
virtual void
f()
{
cout << "B2::f()" << endl;
}
virtual void f2() { cout << "B2::f2()" << endl; }
virtual void Bf2() { cout << "B2::Bf2()" << endl; }
};

class D : public B1,
public B2
{
public:
long id;
char cd;

public:
D() : id(100), cd('D')
{
}
virtual void
f()
{
cout << "D::f()" << endl;
}
virtual void f1() { cout << "D::f1()" << endl; }
virtual void f2() { cout << "D::f2()" << endl; }
virtual void Df() { cout << "D::Df()" << endl; }
};

typedef void (*Fun)(void);
int main()
{
long **pVtab = NULL;

Fun pFun = NULL;

D d;

pVtab = (long **)&d;

cout << "[0] D::B1::_vptr->" << endl;

pFun = (Fun)pVtab[0][0];

cout << " [0] ";
pFun();

pFun = (Fun)pVtab[0][1];

cout << " [1] ";
pFun();

pFun = (Fun)pVtab[0][2];

cout << " [2] ";
pFun();

pFun = (Fun)pVtab[0][3];

cout << " [3] ";
pFun();

pFun = (Fun)pVtab[0][4];

cout << " [4] ";
pFun();

pFun = (Fun)pVtab[0][5];

cout << " [5] 0x" << pFun << endl;

cout << "[1] B::ib = " << (long)pVtab[1] << endl;

cout << "[2] B::cb = " << static_cast<char>((long)(pVtab[2])) << endl;

cout << "[3] B1::ib1 = " << (long)pVtab[3] << endl;

cout << "[4] B1::cb1 = " << (static_cast<char>((long)(pVtab[4]))) << endl;

cout
<< "[5] D::B2::_vptr->" << endl;

pFun = (Fun)pVtab[5][0];

cout << " [0] ";
pFun();

pFun = (Fun)pVtab[5][1];

cout << " [1] ";
pFun();

pFun = (Fun)pVtab[5][2];

cout << " [2] ";
pFun();

pFun = (Fun)pVtab[5][3];

cout << " [3] ";
pFun();
pFun = (Fun)pVtab[5][4];
cout << " [4] 0x" << pFun << endl;
cout << "[6] B::ib = " << (long)pVtab[6] << endl;
cout << "[7] B::cb = " << (static_cast<char>((long)pVtab[7])) << endl;
cout << "[8] B2::ib2 = " << (long)pVtab[8] << endl;
cout << "[9] B2::cb2 = " << (static_cast<char>((long)pVtab[9])) << endl;
cout << "[10] D::id = " << (long)pVtab[10] << endl;
cout << "[11] D::cd = " << (static_cast<char>((long)pVtab[11])) << endl;
}

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[0] D::B1::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f1()
[3] B1::Bf1()
[4] D::f2()
[5] 0x1
[1] B::ib = 0
[2] B::cb = B
[3] B1::ib1 = 11
[4] B1::cb1 = 1
[5] D::B2::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f2()
[3] B2::Bf2()
[4] 0x0
[6] B::ib = 0
[7] B::cb = B
[8] B2::ib2 = 12
[9] B2::cb2 = 2
[10] D::id = 100
[11] D::cd = D

GDB调试

1
2
3
4
5
6
7
x /12x 0x7fffffffcb60
0x7fffffffcb60: 0x0000555555756c58 0x0000000000000123
0x7fffffffcb70: 0x0000555555756c55 0x0000000000000111
0x7fffffffcb80: 0x0000000000000011 0x0000555555756c98
0x7fffffffcb90: 0x0000000000000123 0x0000555555555555
0x7fffffffcba0: 0x0000000000000212 0x0000555555555a22
0x7fffffffcbb0: 0x0000000000000100 0x0000000000000033

虚拟继承

大佬偷懒了,那我们完了啊。

对于这个虚拟继承,和64位机好像有点不一样,我也不知道为啥。
如果有人看懂了回来私信我(留个言也行)。告诉我为啥。

我贴一个自己的实验不保证正确性